//============================================================================
// Name        : NightSearcher.cpp
// Author      : 
// Version     :
// Copyright   : 
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <math.h>
#include <fstream>
#include "ServerSocket.h"
#include "SocketException.h"
#include "CheckPointsCreator.h"
#include "WordMatchesRetriever.h"
#include "VectorModeler.h"
#include "LoadCP.h"
#include "DocMatch.h"
#include "ResultMap.h"
#include "DocVector.h"
#include "Converter.h"
#include "MD5toURL.h"
#include "BlackList.h"
#include "PositionModeler.h"
#include <map>
#include <vector>
using namespace std;

int main() {
	/**
	 * Creating checkpoint 
	 */
//	ifstream in;
//	ofstream out;
//	in.open("c:\\00.txt", ios::in);
//	out.open("c:\\00res.txt", ios::out);
//	CheckPointsCreator::createCPTable(&in,&out);
//	return 0;
	
	/**
	 * Initializing Checkpoints and DataFile
	 */
	double NDocs = 3000000;
	//ifstream data;
	ifstream checkpoints;
	//data.open("/work/FinalC.txt", ios::in);
	checkpoints.open("/work/CPS.txt", ios::in);
	cout << "Started Loading CheckPoints at: " << time(NULL) << endl;
	LoadCP::loadCPMap(&checkpoints);
	cout << "Finished Loading CheckPoints at: " << time(NULL) << endl;
	cout << "Started Loading MD5 Dic at: " << time(NULL) << endl;
	MD5toURL::loadMap("/work/ReverseSiteMD5.txt");
	cout << "Finished Loading MD5 Dic at: " << time(NULL) << endl;
	BlackList::init();
	
	//data.seekg(0,ios::end);
	//cout << "File Size =" << data.tellg() << endl;
	//data.seekg(3900000000,ios::beg);
	//string aux;
	//data >> aux;
	//cout << "AUXXX " << aux << endl;
	
	//return 0;
	try{
	
		ServerSocket server (1234);
	
		/**
		 * Searching for something.. xD
		 */
		 while(true) 
		 {
			ServerSocket new_sock;
			server.accept( new_sock);
			string input;
			new_sock >> input;
			//string input = "sao paulo futebol clube";
			vector<uint> wordlist;
			wordlist = Converter::wordToHash(Converter::parseQuery(input));
			vector<ResultMap> allResults;
			map<string,DocMatch> result;
			// Efetuando a busca por cada palavra desejada!
			// Cada busca retorna um map<string, DocMatch> --> (docMd5, Vetor de posicoes de match)
			// Um elemento do tipo ResultMap armazena dois atributos: wordHash e ResultMap correspondente.
			// Ao final do passo a seguir, um vetor de ResultMap (allResults) armazena os dados necessarios
			// para prosseguir com o processo de busca.
			for(int i=0;i<wordlist.size();i++)
			{			
				result = WordMatchesRetriever::getWordMatches(wordlist[i] ,200);
				allResults.push_back(ResultMap(wordlist[i],result));
			}
			
			//Agora, para cada palavra, passamos pela sua lista de documentos e vamos a cada
			// passo construindo o DocVector para cada documento. O DocVector contem os 
			// coeficientes necessarios para aplicar o modelo vetorial. No final, armazenamos
			// o sistema linear num vetor de DocVectors;		
			
			map<uint,vector<string> > resultPosition;
			resultPosition = PositionModeler::getBestSites(&allResults,&wordlist);
			//map<string,double> resultVectorial;
			
			//resultVectorial = VectorModeler::applyVectorModel(&wordlist,&allResults);	
			//cout << "Finished apllying Vector Model" << endl;
			map<uint,vector<string> >::iterator it;
			int amount=0;
			for(it=resultPosition.begin();it!=resultPosition.end();it++)
			{
				//cout << "Trying to append: " << it->first << endl;
				for(int i=0;i<it->second.size();i++)
				{
					string data = MD5toURL::translate((it->second)[i]);
					if(data!="Call Huston" && it->first < 100000 && amount < 10)
					{
						amount++;
						data.append("\n");
						new_sock << data;
					}
				
				}
			}
			cout << "Finished Search at: " << time(NULL) << endl;
		 }
	}
	catch(SocketException&) {}
		
	checkpoints.close();
	return 0;
	
}
